package com.lepinwenhua.roomdemo;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import java.lang.ref.WeakReference;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.ViewModelProvider;

public class MainActivity extends AppCompatActivity {

    private AppDatabase database;
    private FruitDao fruitDao;
    private TextView resultText;

    //1、内存泄漏的原因：
    //核心问题在于创建的 Handler 是一个匿名内部类。在Java中，非静态内部类（包括匿名内部类）会隐式持有其外部类的引用。
    //在代码中，即 Handler 持有了 MainActivity 的引用。
    //2、这个引用链的形成过程如下：
    //通过 Handler 发送 Message，Message 会进入 MessageQueue 排队等待处理。
    //每个 Message 都持有一个对目标 Handler 的引用（即 Message.target）。
    //由于 Handler 是匿名内部类，它隐式持有 MainActivity 的引用。
    //3、因此，一条强引用链就形成了：
    //MessageQueue → Message → Handler → MainActivity
    //如果 MessageQueue 中还有尚未处理或正在处理的延迟消息时，Activity 被销毁（例如用户按返回键），这条强引用链就会阻止 Activity 被垃圾回收（GC），从而导致内存泄漏。虽然通过 Looper.myLooper() 获取了主线程的 Looper，但这并没有改变 Handler 作为匿名内部类持有 Activity 引用这一事实。
    //4、防护措施与局限
    //虽然已经在 onDestroy() 方法中调用了 handler.removeCallbacksAndMessages(null)，这是一个非常好的实践。这个方法会移除消息队列中所有与该 Handler 相关的消息和回调，从而切断 MessageQueue → Message → Handler 这条引用链。
    //5、然而，这种方法存在一定的局限性：
    //依赖手动调用：如果忘记在 onDestroy 中调用，或者调用时机不当，泄漏依然会发生。
    //并非根本解决：它更像是一种“事后补救”措施，而非从设计上杜绝问题。内存泄漏的风险在 Activity 销毁前、消息未被处理的时段内依然存在。

/*    private final Handler handler = new Handler(Objects.requireNonNull(Looper.myLooper())) {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case 0://数据插入成功
                    resultText.setText("数据插入成功");
                    break;
                case 1://数据查询成功
                    String sb = String.valueOf(msg.obj);
                    resultText.setText(sb);
                    break;

                case 2://数据更新成功
                    resultText.setText("数据更新成功");
                    break;

                case 3://数据删除成功
                    resultText.setText("数据删除成功");
                    break;

            }
        }
    };*/


    //将 Handler 定义为静态内部类，切断与 Activity 的默认强引用。通过 WeakReference 弱引用 Activity，GC 需要时可回收 Activity。有效解决内存泄漏，是处理现有 Handler 代码的经典方案。
    //方案一：静态内部类 + 弱引用代码示例
    private final SafeHandler handler = new SafeHandler(this);

    private static class SafeHandler extends Handler {
        private final WeakReference<MainActivity> mActivityWeakReference;

        SafeHandler(MainActivity activity) {
            mActivityWeakReference = new WeakReference<>(activity);
        }

        @Override
        public void handleMessage(@NonNull Message msg) {
            MainActivity activity = mActivityWeakReference.get();
            if (activity == null) {
                return;
            }
            switch (msg.what) {
                case 0://数据插入成功
                    activity.resultText.setText("数据插入成功");
                    break;
                case 1://数据查询成功
                    String sb = String.valueOf(msg.obj);
                    activity.resultText.setText(sb);
                    break;

                case 2://数据更新成功
                    activity.resultText.setText("数据更新成功");
                    break;

                case 3://数据删除成功
                    activity.resultText.setText("数据删除成功");
                    break;

            }
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 初始化数据库
        database = MyApplication.getDatabase();
        fruitDao = database.fruitDao();

        resultText = findViewById(R.id.result_text);
        Button insertBtn = findViewById(R.id.insert_btn);
        Button queryBtn = findViewById(R.id.query_btn);
        Button updateBtn = findViewById(R.id.update_btn);
        Button deleteBtn = findViewById(R.id.delete_btn);

//        // 插入数据
//        insertBtn.setOnClickListener((v) -> {
//            //子线程插入数据
//            new Thread(() -> {
//                //插入全部数据
//                fruitDao.insertAll(new Fruit("苹果", 5.5f),
//                        new Fruit("香蕉", 3.2f),
//                        new Fruit("橙子", 4.8f));
//                handler.sendEmptyMessage(0);
//            }).start();
//        });
//
//        // 查询数据
//        queryBtn.setOnClickListener((v) -> {
//            //子线程查询数据
//            new Thread(() -> {
//                List<Fruit> fruits = fruitDao.getAllFruits();
//                StringBuilder sb = new StringBuilder("所有水果:\n");
//                for (Fruit fruit : fruits) {
//                    sb.append(fruit.toString()).append("\n");
//                }
//                //通过handler把数据传递到主线程更新
//                Message message = new Message();
//                message.what = 1;
//                message.obj = sb.toString();
//                handler.sendMessage(message);
//            }).start();
//        });
//
//        // 更新数据
//        updateBtn.setOnClickListener((v) -> {
//            //子线程更新数据
//            new Thread(() -> {
//                List<Fruit> fruits = fruitDao.getAllFruits();
//                if (!fruits.isEmpty()) {
//                    Fruit firstFruit = fruits.get(0);
//                    firstFruit.setPrice(6.0f); // 更新价格
//                    fruitDao.update(firstFruit);
//                }
//                handler.sendEmptyMessage(2);
//            }).start();
//        });
//
//        // 删除数据
//        deleteBtn.setOnClickListener((v) -> {
//            //子线程删除数据
//            new Thread(() -> {
//                List<Fruit> fruits = fruitDao.getAllFruits();
//                if (!fruits.isEmpty()) {
//                    fruitDao.delete(fruits.get(0)); // 删除第一条数据
//                }
//                handler.sendEmptyMessage(3);
//            }).start();
//        });


        // 初始化 ViewModel
        FruitViewModelFactory factory = new FruitViewModelFactory(getApplication());
        FruitViewModel fruitViewModel = new ViewModelProvider(this, factory).get(FruitViewModel.class);
        // 观察数据变化，自动更新UI！这是最核心的部分。
        fruitViewModel.getAllFruits().observe(this, fruits -> {
            StringBuilder sb = new StringBuilder("所有水果:\n");
            for (Fruit fruit : fruits) {
                sb.append(fruit.toString()).append("\n");
            }
            resultText.setText(sb.toString());
        });
        // 插入数据 - 现在只需调用ViewModel的方法，UI会自动更新
        insertBtn.setOnClickListener(v -> {
            fruitViewModel.insertAll(
                    new Fruit("苹果", 5.5f),
                    new Fruit("香蕉", 3.2f),
                    new Fruit("橙子", 4.8f)
            );
            // 不再需要手动发送Handler消息！
            // 当数据库插入完成，上面的观察者会自动被触发。
        });

        // 查询按钮现在可以移除，因为数据变化会自动通知。
        // 但如果你需要手动刷新，可以保留并调用一个刷新方法（如果ViewModel里有的话）
        queryBtn.setVisibility(View.GONE); // 或者直接隐藏按钮

        // 更新数据
        updateBtn.setOnClickListener(v -> {
            // 注意：这里为了演示，仍然需要先获取列表再更新第一条。
            // 在实际项目中，你可能需要通过ID来定位要更新的项。
            new Thread(() -> {
                // 这是一个临时方案。更佳实践是在ViewModel中提供根据ID更新等方法。
                Fruit firstFruit = fruitViewModel.getAllFruits().getValue() != null ?
                        fruitViewModel.getAllFruits().getValue().get(0) : null;
                if (firstFruit != null) {
                    firstFruit.setPrice(6.0f);
                    fruitViewModel.update(firstFruit);
                }
            }).start();
        });

        // 删除数据
        deleteBtn.setOnClickListener(v -> {
            new Thread(() -> {
                Fruit firstFruit = fruitViewModel.getAllFruits().getValue() != null ?
                        fruitViewModel.getAllFruits().getValue().get(0) : null;
                if (firstFruit != null) {
                    fruitViewModel.delete(firstFruit);
                }
            }).start();
        });

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //如果使用ViewModel 和 LiveData 架构（不再需要手动关闭数据库和清理Handler，框架会自动管理。）
        // if (database != null) { database.close(); }
        // if (handler != null) { handler.removeCallbacksAndMessages(null); }




//        if (database != null) {
//            database.close();//关闭数据库
//        }
        //场景：假设通过Handler发送了一条延迟 10 分钟的消息来更新 UI。在消息被处理前，用户就关闭了 Activity。
        //仅有弱引用：Activity 会很快被 GC 回收，避免了内存泄漏。这很好！但是，10分钟后，那条延迟消息依然会触发，Handler 的 handleMessage 方法仍会执行。当尝试通过弱引用获取 Activity 时，activity == null 条件成立，方法直接返回。虽然不会崩溃，但这意味着系统白白进行了一次无用的消息处理。如果存在多个这样的无效消息，就是一种资源浪费。
        //弱引用 + removeCallbacksAndMessages(null)：在 onDestroy 中，清除了这条延迟消息。当 10 分钟过后，消息队列中已经没有了这条消息，什么也不会发生。这更加干净利落，既避免了内存泄漏，也避免了无效的逻辑操作。
        //因此，弱引用是“被动防御”，而 removeCallbacksAndMessages 是“主动清理”。双管齐下，代码会更加健壮。
        //最佳实践总结
        //SafeHandler（弱引用类集成Handler） 结合 onDestroy 中的清理操作，是一个非常标准和安全的做法。请保持这个好习惯。
        //简单来说：
        //弱引用管“泄漏”，removeCallbacksAndMessages 管“无效操作”。两者结合，万无一失。
//        if (handler!=null){
//            handler.removeCallbacksAndMessages(null);//清理Handler
//        }
    }
}